From bc6aaa19edc8419f0244abb275bc4b94787da7ab Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Tue, 28 Jun 2011 01:09:02 +0000 Subject: [PATCH] * Added truncate() & truncateHTML() tests * Some fixes/changes to truncateHTML() based on tests ** Something like "hello" ends up as "..." instead of just "..." for relevant cases) ** If we get something like " $dispLen in truncateHTML() --- languages/Language.php | 36 ++++---- tests/phpunit/languages/LanguageTest.php | 102 +++++++++++++++++++++++ 2 files changed, 122 insertions(+), 16 deletions(-) diff --git a/languages/Language.php b/languages/Language.php index 79397132d0..06b39bd338 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -2770,31 +2770,33 @@ class Language { return $text; // string short enough even *with* HTML (short-circuit) } - $displayLen = 0; // innerHTML legth so far + $dispLen = 0; // innerHTML legth so far $testingEllipsis = false; // checking if ellipses will make string longer/equal? $tagType = 0; // 0-open, 1-close $bracketState = 0; // 1-tag start, 2-tag name, 0-neither $entityState = 0; // 0-not entity, 1-entity - $tag = $ret = $pRet = ''; // accumulated tag name, accumulated result string + $tag = $ret = ''; // accumulated tag name, accumulated result string $openTags = array(); // open tag stack - $pOpenTags = array(); + $maybeState = null; // possible truncation state $textLen = strlen( $text ); $neLength = max( 0, $length - strlen( $ellipsis ) ); // non-ellipsis len if truncated for ( $pos = 0; true; ++$pos ) { # Consider truncation once the display length has reached the maximim. + # We check if $dispLen > 0 to grab tags for the $neLength = 0 case. # Check that we're not in the middle of a bracket/entity... - if ( $displayLen >= $neLength && $bracketState == 0 && $entityState == 0 ) { + if ( $dispLen && $dispLen >= $neLength && $bracketState == 0 && !$entityState ) { if ( !$testingEllipsis ) { $testingEllipsis = true; # Save where we are; we will truncate here unless there turn out to # be so few remaining characters that truncation is not necessary. - $pOpenTags = $openTags; // save state - $pRet = $ret; // save state - } elseif ( $displayLen > $length && $displayLen > strlen( $ellipsis ) ) { + if ( !$maybeState ) { // already saved? ($neLength = 0 case) + $maybeState = array( $ret, $openTags ); // save state + } + } elseif ( $dispLen > $length && $dispLen > strlen( $ellipsis ) ) { # String in fact does need truncation, the truncation point was OK. - $openTags = $pOpenTags; // reload state - $ret = $this->removeBadCharLast( $pRet ); // reload state, multi-byte char fix + list( $ret, $openTags ) = $maybeState; // reload state + $ret = $this->removeBadCharLast( $ret ); // multi-byte char fix $ret .= $ellipsis; // add ellipsis break; } @@ -2832,25 +2834,27 @@ class Language { if ( $entityState ) { if ( $ch == ';' ) { $entityState = 0; - $displayLen++; // entity is one displayed char + $dispLen++; // entity is one displayed char } } else { + if ( $neLength == 0 && !$maybeState ) { + // Save state without $ch. We want to *hit* the first + // display char (to get tags) but not *use* it if truncating. + $maybeState = array( substr( $ret, 0, -1 ), $openTags ); + } if ( $ch == '&' ) { $entityState = 1; // entity found, (e.g. " ") } else { - $displayLen++; // this char is displayed + $dispLen++; // this char is displayed // Add the next $max display text chars after this in one swoop... - $max = ( $testingEllipsis ? $length : $neLength ) - $displayLen; + $max = ( $testingEllipsis ? $length : $neLength ) - $dispLen; $skipped = $this->truncate_skip( $ret, $text, "<>&", $pos + 1, $max ); - $displayLen += $skipped; + $dispLen += $skipped; $pos += $skipped; } } } } - if ( $displayLen == 0 ) { - return ''; // no text shown, nothing to format - } // Close the last tag if left unclosed by bad HTML $this->truncate_endBracket( $tag, $text[$textLen - 1], $tagType, $openTags ); while ( count( $openTags ) > 0 ) { diff --git a/tests/phpunit/languages/LanguageTest.php b/tests/phpunit/languages/LanguageTest.php index 085420e3fe..34baea8b8a 100644 --- a/tests/phpunit/languages/LanguageTest.php +++ b/tests/phpunit/languages/LanguageTest.php @@ -112,6 +112,108 @@ class LanguageTest extends MediaWikiTestCase { ); } + function testTruncate() { + $this->assertEquals( + "XXX", + $this->lang->truncate( "1234567890", 0, 'XXX' ), + 'truncate prefix, len 0, small ellipsis' + ); + + $this->assertEquals( + "12345XXX", + $this->lang->truncate( "1234567890", 8, 'XXX' ), + 'truncate prefix, small ellipsis' + ); + + $this->assertEquals( + "123456789", + $this->lang->truncate( "123456789", 5, 'XXXXXXXXXXXXXXX' ), + 'truncate prefix, large ellipsis' + ); + + $this->assertEquals( + "XXX67890", + $this->lang->truncate( "1234567890", -8, 'XXX' ), + 'truncate suffix, small ellipsis' + ); + + $this->assertEquals( + "123456789", + $this->lang->truncate( "123456789", -5, 'XXXXXXXXXXXXXXX' ), + 'truncate suffix, large ellipsis' + ); + } + + /** + * @dataProvider provideHTMLTruncateData() + */ + function testTruncateHTML( $len, $ellipsis, $input, $expected ) { + // Actual HTML... + $this->assertEquals( + $expected, + $this->lang->truncateHTML( $input, $len, $ellipsis ) + ); + } + + /** + * Array format is ($len, $ellipsis, $input, $expected) + */ + function provideHTMLTruncateData() { + return array( + array( 0, 'XXX', "1234567890", "XXX" ), + array( 8, 'XXX', "1234567890", "12345XXX" ), + array( 5, 'XXXXXXXXXXXXXXX', '1234567890', "1234567890" ), + array( 2, '***', + '

', + '

', + ), + array( 2, '***', + '

123456789

', + '

***

', + ), + array( 2, '***', + '

 23456789

', + '

***

', + ), + array( 3, '***', + '

123456789

', + '

***

', + ), + array( 4, '***', + '

123456789

', + '

1***

', + ), + array( 5, '***', + '123456789', + '12***', + ), + array( 6, '***', + '

123456789

', + '

123***

', + ), + array( 6, '***', + '

12 456789

', + '

12 ***

', + ), + array( 7, '***', + '123

456

789
', + '123

4***

', + ), + array( 8, '***', + '
123456789
', + '
12345***
', + ), + array( 9, '***', + '

123456789

', + '

123456789

', + ), + array( 10, '***', + '

123456789

', + '

123456789

', + ), + ); + } + /** * Test Language::isValidBuiltInCode() * @dataProvider provideLanguageCodes -- 2.20.1